package com.smh.demo1.a21;

import com.smh.demo1.common.LogColour;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.Set;

/**
 * @author shiminghui
 * @date 2025/5/1 18:50
 * @description: TODO
 */
public class A21 {
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {

        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(WebConfig.class);

        RequestMappingHandlerAdapter adapter = new RequestMappingHandlerAdapter();
        adapter.setApplicationContext(context);
        adapter.afterPropertiesSet();   // 全局的initBinder 会执行,Controller里面的initBinder 不会执行
        showBindMethods(adapter);

        // 模拟收到web请求, 这时controller里面的initBinder 才会执行,即接收到第一次请求时执行,然后缓存起来
        Method getDataBinderFactory = adapter.getClass().getDeclaredMethod("getDataBinderFactory", HandlerMethod.class);
        getDataBinderFactory.setAccessible(true);

        getDataBinderFactory.invoke(adapter, new HandlerMethod(new WebConfig.Controller1(), WebConfig.Controller1.class.getMethod("test")));
        showBindMethods(adapter);

        getDataBinderFactory.invoke(adapter, new HandlerMethod(new WebConfig.Controller2(), WebConfig.Controller2.class.getMethod("test")));
        showBindMethods(adapter);


        context.close();

    }

    public static void showBindMethods(RequestMappingHandlerAdapter adapter) {
        try {
            Field field = adapter.getClass().getDeclaredField("initBinderCache");
            field.setAccessible(true);
            Map map = (Map) field.get(adapter);
            Set set = map.entrySet();
            for (Object o : set) {
                Map.Entry entry = (Map.Entry) o;
                System.out.println(LogColour.Blue(entry.getKey() + "-->" + entry.getValue()));
            }
            System.out.println("-----------------------------");
            Field field2 = adapter.getClass().getDeclaredField("initBinderAdviceCache");
            field2.setAccessible(true);
            Map map2 = (Map) field2.get(adapter);
            Set set2 = map2.entrySet();
            for (Object o : set2) {
                Map.Entry entry = (Map.Entry) o;
                System.out.println(LogColour.Blue(entry.getKey() + "-->" + entry.getValue()));
            }
            System.out.println();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
